//Filename	 : lcd.c	

//Author	 : Thomas A. McDonley (darkeyes@ufl.edu, darkeyes_z@hotmail.com)
//Description: 
//Copyright	: (C) 2007
//EULA		: GNU

/*	LCD Hitachi HD44780u in 4bit mode
	Copyright (C) 2007  Thomas A. McDonley

	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#include <avr/io.h>
#include <util/delay.h>

#include "lcd.h"

//=================================================================================================
//Description:		
//Precondition:	
//Postcondition:	
//Returns:
void
lcd_init(void)
{
	DDRC |=	0xFF;					//PORTC(6) is Enable
									//PORTC 5-0 = R/W | RS | DB7 | DB6 | DB5 | DB4
	/* Delay for 15ms to allow VCC to settle */
	_delay_ms(15);

	/* Manual Initialization of LCD Driver */
	lcd_writeCmd(0x33, 5, 1);

	/* Four bit operation */
	lcd_writeCmd(0x32, 5, 2);

	/* Enable 2 lines */
	lcd_writeCmd(0x28, 1, 2);

	/* Display on; Cursor On; Blink On */
	lcd_writeCmd(0x0C, 1, 2);

	/* Clear Screen; Cursor Home */
	lcd_writeCmd(0x01, 1, 2);
}
//=================================================================================================


//=================================================================================================
//Description:		Abstracts how commands are written to the LCD driver	
//Precondition: 	The lcd has been init and is in 4 bit mode
//Postcondition:	The command has been executed
//Returns:
void lcd_writeCmd(uint8_t cmd, uint8_t wdelay, uint8_t edelay)
{
  PORTC = ( (cmd & 0xF0) >> 4) | 0x40;		//Write upper nibble to cmd register
  PORTC ^= 0x40;							//  Enable = 0... Falling edge signals to read bus

  _delay_ms(wdelay);						//Delay 1ms for write to settle [Hold time > 100us]

  PORTC = ( (cmd & 0x0F) ) | 0x40;			//Write lower nibble to cmd register
  PORTC ^= 0x40;

  _delay_ms(edelay);						//Delay 2ms (Wait for instruction to execute)
}
//=================================================================================================

//=================================================================================================
//Description:		Abstracts how data is written to the LCD	
//Precondition:		the lcd has been init and is in 4 bit mode
//Postcondition:	The character appears on the screen at the current cursor posistion
//Returns:
void lcd_writeData(uint8_t data, uint8_t wdelay, uint8_t edelay)
{
  PORTC = ( (data & 0xF0) >> 4) | 0x40 | 0x10;//Write upper nibble to cmd register... Enable = 1... RS = Data register
  PORTC ^= 0x40;							//  Enable = 0... Falling edge signals to read bus

  _delay_ms(wdelay);						//Delay 1ms for write to settle [Hold time > 100us]

  PORTC = ( (data & 0x0F) ) | 0x40 | 0x10;	//Write lower nibble to cmd register
  PORTC ^= 0x40;

  _delay_ms(edelay);						//Delay 2ms (Wait for instruction to execute)
}
//=================================================================================================


//=================================================================================================
//Description:		Shifts the display either right or left	
//Precondition:		dir is equal to 0 to shift left and 1 to shift right
//Postcondition:	display has been shifted
//Returns:
void lcd_shiftDisplay(uint8_t dir)
{
	if(dir == 0)
		lcd_writeCmd(0x1C, 1, 2);
	else
		lcd_writeCmd(0x18, 1, 2);

}
//=================================================================================================


//=================================================================================================
//Description:		Turns the lcd display off
//Precondition:	
//Postcondition: 	The display is off
//Returns:
void lcd_off()
{
	lcd_writeCmd(0x08, 1, 2);
}
//=================================================================================================


//=================================================================================================
//Description:		Turns the lcd display on
//Precondition:		Cursor and blink are set according to what is desired to be on
//Postcondition: 	The display is on
//Returns:
void lcd_on(uint8_t cursor, uint8_t blink)
{
	if(!cursor && !blink) 		lcd_writeCmd(0x0C, 1, 2);
	else if(cursor && blink) 	lcd_writeCmd(0x0F, 1, 2);
	else 						lcd_writeCmd(0x0E, 1, 2);
}
//=================================================================================================


//=================================================================================================
//Description:		Take the cursor to the beginning of a line
//Precondition:		home = 0 for first line, 1 for second
//Postcondition: 	The cursor is at the beginning of a line
//Returns:
void lcd_home(uint8_t home)
{
	if (home == 0)
		lcd_writeCmd(0x02, 1, 2);
	else
		lcd_writeCmd(0xC0, 1, 2);
}
//=================================================================================================


//=================================================================================================
//Description:		Prints a null terminated character array to the LCD. '\n' will cause it to goto line 2	
//Precondition:		string != NULL and is a pointer to a character array. ex: lcd_print("Hello /nWorld!")
//Postcondition: 	
//Returns:
void
lcd_print(char *string)
{
	while (*string) {
		if (*string == '\n')
			lcd_home(1);
		else
			lcd_writeData(*string, 0, 1);

		++string;
	}
}
//=================================================================================================

//=================================================================================================
//Description:		Clears the LCD screen and moves the cursor to line0 home	
//Precondition:		
//Postcondition: 	
//Returns:
void
lcd_clrscr(void)
{
	lcd_writeCmd(0x01, 0, 2);
}
//=================================================================================================
